package com.vehicle.coupon.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import ch.qos.logback.core.joran.spi.XMLUtil;
import com.alibaba.fastjson.JSON;
import com.vehicle.common.core.domain.R;
import com.vehicle.coupon.domain.CouponRecord;
import com.vehicle.coupon.service.ICouponRecordService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.vehicle.coupon.mapper.CouponMapper;
import com.vehicle.coupon.domain.Coupon;
import com.vehicle.coupon.service.ICouponService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 优惠券Service业务层处理
 *
 * @author XU
 * @date 2025-03-25
 */
@Service
public class CouponServiceImpl implements ICouponService {
    
    @Autowired
    private CouponMapper couponMapper;
    
    @Autowired
    private ICouponRecordService couponRecordService;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private static final String COUPON_STOCK_KEY = "coupon:stock:";
    private static final String COUPON_LOCK_KEY = "coupon:lock:";
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean issueCoupon(Long couponId, Long userId, Long targetUserId) {
        // 1. 检查优惠券状态
        Coupon coupon1 = couponMapper.selectCouponById(couponId);
        if (coupon1 == null) {
            throw new RuntimeException("优惠券不存在");
        }
        
        // 检查优惠券是否在有效期内
        Date now = new Date();
        if (now.before(coupon1.getStartTime())) {
            throw new RuntimeException("优惠券活动未开始");
        }
        if (now.after(coupon1.getEndTime())) {
            throw new RuntimeException("优惠券活动已结束");
        }
    
        // 2. 检查用户是否已领取该优惠券
        if (couponMapper.checkUserReceived(couponId, targetUserId) > 0) {
            throw new RuntimeException("该用户已领取过此优惠券");
        }

        // 2. 使用Redis分布式锁防止重复提交
        String lockKey = COUPON_LOCK_KEY + couponId + ":" + targetUserId;
        boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
        if (!locked) {
            throw new RuntimeException("请勿重复提交");
        }

        String stockKey = null;
        try {
            // 3. Redis预减库存
            stockKey = COUPON_STOCK_KEY + couponId;
            Long stock = redisTemplate.opsForValue().decrement(stockKey);
            if (stock < 0) {
                redisTemplate.opsForValue().increment(stockKey);
                return false;
            }

            // 4. 数据库乐观锁更新
            Coupon coupon = couponMapper.selectCouponById(couponId);
            if (coupon == null || coupon.getRemaining() <= 0) {
                throw new RuntimeException("优惠券库存不足");
            }

            int result = couponMapper.decreaseStock(couponId, coupon.getVersion());
            if (result <= 0) {
                throw new RuntimeException("领取失败，请重试");
            }

            // 5. 插入领取记录
            CouponRecord record = new CouponRecord();
            record.setCouponId(couponId);
            record.setUserId(targetUserId);  // 设置领取用户ID
            record.setGetTime(new Date());
            record.setStatus(0);
            record.setUserId(userId);  // 设置发放人ID
            couponRecordService.insertCouponRecord(record);
            
            return true;
        } catch (Exception e) {
            // 发生异常，回滚Redis库存
            redisTemplate.opsForValue().increment(stockKey);
            throw e;
        } finally {
            // 释放分布式锁
            redisTemplate.delete(lockKey);
        }
    }

    @Override
    public void insertCouponRecord(CouponRecord record) {
        couponRecordService.insertCouponRecord(record);
    }

    @Override
    public Coupon selectCouponById(Long id) {
        return couponMapper.selectCouponById(id);
    }

    @Override
    public List<Coupon> selectCouponList(Coupon coupon) {
        return couponMapper.selectCouponList(coupon);
    }

    @Override
    public int insertCoupon(Coupon coupon) {
        return couponMapper.insertCoupon(coupon);
    }

    @Override
    public int updateCoupon(Coupon coupon) {
        return couponMapper.updateCoupon(coupon);
    }

    @Override
    public int deleteCouponByIds(Long[] ids) {
        return couponMapper.deleteCouponByIds(ids);
    }

    @Override
    public int deleteCouponById(Long id) {
        return couponMapper.deleteCouponById(id);
    }
    
    @PostConstruct
    public void initStock() {
        List<Coupon> coupons = couponMapper.selectCouponList(new Coupon());
        for (Coupon coupon : coupons) {
            String stockKey = COUPON_STOCK_KEY + coupon.getId();
            redisTemplate.opsForValue().set(stockKey, String.valueOf(coupon.getRemaining()));
        }
    }






}
